ஜாவாஸ்கிரிப்ட் அசிங்க் இட்டரேட்டர் ஹெல்பர் 'ஸ்கேன்'-இன் செயல்பாடு, பயன்பாட்டு வழக்குகள் மற்றும் அசிங்க்ரோனஸ் திரட்டல் செயலாக்கத்திற்கான அதன் நன்மைகளை ஆராயும் ஒரு ஆழமான பார்வை.
ஜாவாஸ்கிரிப்ட் அசிங்க் இட்டரேட்டர் ஹெல்பர்: ஸ்கேன் - அசிங்க் திரட்டல் செயலாக்கம்
நவீன ஜாவாஸ்கிரிப்ட் மேம்பாட்டில் அசிங்க்ரோனஸ் புரோகிராமிங் ஒரு மூலக்கல்லாக உள்ளது, குறிப்பாக நெட்வொர்க் கோரிக்கைகள் அல்லது கோப்பு முறைமை ஊடாடல்கள் போன்ற I/O-சார்ந்த செயல்பாடுகளை கையாளும் போது. ES2018-ல் அறிமுகப்படுத்தப்பட்ட அசிங்க் இட்டரேட்டர்கள், அசிங்க்ரோனஸ் தரவு ஓடைகளைக் கையாளுவதற்கு ஒரு சக்திவாய்ந்த வழிமுறையை வழங்குகின்றன. RxJS போன்ற லைப்ரரிகளில் அடிக்கடி காணப்படும் மற்றும் தனிப்பட்ட பயன்பாடாகவும் கிடைக்கும் `scan` ஹெல்பர், இந்த அசிங்க்ரோனஸ் தரவு ஓடைகளைச் செயலாக்குவதற்கான மேலும் பல சாத்தியக்கூறுகளைத் திறக்கிறது.
அசிங்க் இட்டரேட்டர்களைப் புரிந்துகொள்ளுதல்
`scan`-ஐப் பற்றி விரிவாகப் பார்ப்பதற்கு முன், அசிங்க் இட்டரேட்டர்கள் என்றால் என்ன என்பதை நினைவு கூர்வோம். ஒரு அசிங்க் இட்டரேட்டர் என்பது அசிங்க் இட்டரேட்டர் புரோட்டோகாலுக்கு இணங்கக்கூடிய ஒரு ஆப்ஜெக்ட் ஆகும். இந்த புரோட்டோகால் ஒரு `next()` முறையை வரையறுக்கிறது, அது ஒரு ப்ராமிஸை வழங்குகிறது. அந்த ப்ராமிஸ் இரண்டு பண்புகளுடன் கூடிய ஒரு ஆப்ஜெக்ட்டாகத் தீர்க்கப்படுகிறது: `value` (வரிசையில் அடுத்த மதிப்பு) மற்றும் `done` (இட்டரேட்டர் முடிந்துவிட்டதா என்பதைக் குறிக்கும் ஒரு பூலியன்). காலப்போக்கில் வந்து சேரும் தரவுகளுடன் அல்லது பெறுவதற்கு அசிங்க்ரோனஸ் செயல்பாடுகள் தேவைப்படும் தரவுகளுடன் பணிபுரியும் போது அசிங்க் இட்டரேட்டர்கள் குறிப்பாக பயனுள்ளதாக இருக்கும்.
இங்கே ஒரு அசிங்க் இட்டரேட்டரின் அடிப்படை உதாரணம்:
async function* generateNumbers() {
yield 1;
yield 2;
yield 3;
}
async function main() {
const iterator = generateNumbers();
let result = await iterator.next();
console.log(result); // { value: 1, done: false }
result = await iterator.next();
console.log(result); // { value: 2, done: false }
result = await iterator.next();
console.log(result); // { value: 3, done: false }
result = await iterator.next();
console.log(result); // { value: undefined, done: true }
}
main();
`scan` ஹெல்பர் அறிமுகம்
`scan` ஹெல்பர் ( `accumulate` அல்லது `reduce` என்றும் அழைக்கப்படுகிறது) ஒவ்வொரு மதிப்பிற்கும் ஒரு அக்குமுலேட்டர் செயல்பாட்டைப் பயன்படுத்துவதன் மூலம் ஒரு அசிங்க் இட்டரேட்டரை மாற்றியமைக்கிறது மற்றும் திரட்டப்பட்ட முடிவை வெளியிடுகிறது. இது அரேக்களில் உள்ள `reduce` முறைக்கு ஒப்பானது, ஆனால் இது அசிங்க்ரோனஸாக மற்றும் இட்டரேட்டர்களில் செயல்படுகிறது.
சுருக்கமாக, `scan` ஒரு அசிங்க் இட்டரேட்டர், ஒரு அக்குமுலேட்டர் செயல்பாடு மற்றும் ஒரு விருப்பத்தேர்வு ஆரம்ப மதிப்பைப் பெறுகிறது. மூல இட்டரேட்டரால் வெளியிடப்படும் ஒவ்வொரு மதிப்பிற்கும், முந்தைய திரட்டப்பட்ட மதிப்பு (அல்லது இது முதல் மறு செய்கையாக இருந்தால் ஆரம்ப மதிப்பு) மற்றும் இட்டரேட்டரிலிருந்து தற்போதைய மதிப்புடன் அக்குமுலேட்டர் செயல்பாடு அழைக்கப்படுகிறது. அக்குமுலேட்டர் செயல்பாட்டின் முடிவு அடுத்த திரட்டப்பட்ட மதிப்பாக மாறுகிறது, அது பின்னர் வெளியாகும் அசிங்க் இட்டரேட்டரால் வெளியிடப்படுகிறது.
தொடரியல் மற்றும் அளவுருக்கள்
`scan`-ஐப் பயன்படுத்துவதற்கான பொதுவான தொடரியல் பின்வருமாறு:
async function* scan(sourceIterator, accumulator, initialValue) {
let accumulatedValue = initialValue;
for await (const value of sourceIterator) {
accumulatedValue = accumulator(accumulatedValue, value);
yield accumulatedValue;
}
}
- `sourceIterator`: மாற்றியமைக்க வேண்டிய அசிங்க் இட்டரேட்டர்.
- `accumulator`: இரண்டு வாதங்களை எடுக்கும் ஒரு செயல்பாடு: முந்தைய திரட்டப்பட்ட மதிப்பு மற்றும் இட்டரேட்டரிலிருந்து தற்போதைய மதிப்பு. இது புதிய திரட்டப்பட்ட மதிப்பைத் திரும்ப அளிக்க வேண்டும்.
- `initialValue` (விருப்பத்தேர்வு): அக்குமுலேட்டருக்கான ஆரம்ப மதிப்பு. வழங்கப்படாவிட்டால், மூல இட்டரேட்டரிலிருந்து முதல் மதிப்பு ஆரம்ப மதிப்பாகப் பயன்படுத்தப்படும், மற்றும் அக்குமுலேட்டர் செயல்பாடு இரண்டாவது மதிப்பிலிருந்து அழைக்கப்படும்.
பயன்பாட்டு வழக்குகள் மற்றும் எடுத்துக்காட்டுகள்
`scan` ஹெல்பர் நம்பமுடியாத அளவிற்கு பல்துறை திறன் வாய்ந்தது மற்றும் அசிங்க்ரோனஸ் தரவு ஓடைகள் சம்பந்தப்பட்ட பரந்த அளவிலான சூழ்நிலைகளில் பயன்படுத்தப்படலாம். இங்கே சில எடுத்துக்காட்டுகள்:
1. இயங்கும் மொத்தத்தைக் கணக்கிடுதல்
பரிவர்த்தனைத் தொகைகளை வெளியிடும் ஒரு அசிங்க் இட்டரேட்டர் உங்களிடம் இருப்பதாக கற்பனை செய்து கொள்ளுங்கள். இந்தப் பரிவர்த்தனைகளின் இயங்கும் மொத்தத்தைக் கணக்கிட `scan`-ஐப் பயன்படுத்தலாம்.
async function* generateTransactions() {
yield 10;
yield 20;
yield 30;
}
async function main() {
const transactions = generateTransactions();
const runningTotals = scan(transactions, (acc, value) => acc + value, 0);
for await (const total of runningTotals) {
console.log(total); // Output: 10, 30, 60
}
}
main();
இந்த எடுத்துக்காட்டில், `accumulator` செயல்பாடு தற்போதைய பரிவர்த்தனைத் தொகையை முந்தைய மொத்தத்துடன் சேர்க்கிறது. 0 என்ற `initialValue` இயங்கும் மொத்தம் பூஜ்ஜியத்தில் தொடங்குவதை உறுதி செய்கிறது.
2. தரவை ஒரு அரேவில் திரட்டுதல்
ஒரு அசிங்க் இட்டரேட்டரிலிருந்து தரவை ஒரு அரேவில் திரட்ட `scan`-ஐப் பயன்படுத்தலாம். காலப்போக்கில் தரவைச் சேகரித்து அதைத் தொகுதிகளாகச் செயலாக்குவதற்கு இது பயனுள்ளதாக இருக்கும்.
async function* fetchData() {
yield { id: 1, name: 'Alice' };
yield { id: 2, name: 'Bob' };
yield { id: 3, name: 'Charlie' };
}
async function main() {
const dataStream = fetchData();
const accumulatedData = scan(dataStream, (acc, value) => [...acc, value], []);
for await (const data of accumulatedData) {
console.log(data); // Output: [{id: 1, name: 'Alice'}], [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}], [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}, {id: 3, name: 'Charlie'}]
}
}
main();
இங்கே, `accumulator` செயல்பாடு ஸ்ப்ரெட் ஆபரேட்டரைப் (`...`) பயன்படுத்தி முந்தைய அனைத்து கூறுகளையும் தற்போதைய மதிப்பையும் கொண்ட ஒரு புதிய அரேவை உருவாக்குகிறது. `initialValue` ஒரு வெற்று அரே ஆகும்.
3. ஒரு ரேட் லிமிட்டரை செயல்படுத்துதல்
ஒரு சிக்கலான பயன்பாட்டு வழக்கு ஒரு ரேட் லிமிட்டரை செயல்படுத்துவதாகும். ஒரு குறிப்பிட்ட நேர சாளரத்திற்குள் செய்யப்பட்ட கோரிக்கைகளின் எண்ணிக்கையைக் கண்காணிக்க மற்றும் விகித வரம்பு மீறப்பட்டால் அடுத்தடுத்த கோரிக்கைகளை தாமதப்படுத்த `scan`-ஐப் பயன்படுத்தலாம்.
async function* generateRequests() {
// Simulate incoming requests
yield Date.now();
await new Promise(resolve => setTimeout(resolve, 200));
yield Date.now();
await new Promise(resolve => setTimeout(resolve, 100));
yield Date.now();
}
async function main() {
const requests = generateRequests();
const rateLimitWindow = 1000; // 1 second
const maxRequestsPerWindow = 2;
async function* rateLimitedRequests(source, window, maxRequests) {
let queue = [];
for await (const requestTime of source) {
queue.push(requestTime);
queue = queue.filter(t => requestTime - t < window);
if (queue.length > maxRequests) {
const earliestRequest = queue[0];
const delay = window - (requestTime - earliestRequest);
console.log(`Rate limit exceeded. Delaying for ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
yield requestTime;
}
}
const limited = rateLimitedRequests(requests, rateLimitWindow, maxRequestsPerWindow);
for await (const requestTime of limited) {
console.log(`Request processed at ${requestTime}`);
}
}
main();
இந்த எடுத்துக்காட்டு, கோரிக்கை நேர முத்திரைகளின் வரிசையை பராமரிக்க `scan`-ஐ உள்நாட்டில் (`rateLimitedRequests` செயல்பாட்டில்) பயன்படுத்துகிறது. விகித வரம்பு சாளரத்திற்குள் கோரிக்கைகளின் எண்ணிக்கை அனுமதிக்கப்பட்ட அதிகபட்சத்தை விட அதிகமாக உள்ளதா என்பதை இது சரிபார்க்கிறது. அவ்வாறு இருந்தால், அது தேவையான தாமதத்தைக் கணக்கிட்டு, கோரிக்கையை அளிப்பதற்கு முன்பு இடைநிறுத்துகிறது.
4. ஒரு நிகழ்நேர தரவு திரட்டியை உருவாக்குதல் (உலகளாவிய எடுத்துக்காட்டு)
பல்வேறு பரிமாற்றங்களிலிருந்து நிகழ்நேர பங்கு விலைகளைத் திரட்ட வேண்டிய ஒரு உலகளாவிய நிதி பயன்பாட்டைக் கவனியுங்கள். நியூயார்க் பங்குச் சந்தை (NYSE), லண்டன் பங்குச் சந்தை (LSE), மற்றும் டோக்கியோ பங்குச் சந்தை (TSE) போன்ற பரிமாற்றங்களிலிருந்து விலை புதுப்பிப்புகளை ஒரு அசிங்க் இட்டரேட்டர் ஸ்ட்ரீம் செய்யலாம். `scan`-ஐப் பயன்படுத்தி அனைத்து பரிமாற்றங்களிலும் ஒரு குறிப்பிட்ட பங்கிற்கான இயங்கும் சராசரி அல்லது உயர்/குறைந்த விலையை பராமரிக்க முடியும்.
// Simulate streaming stock prices from different exchanges
async function* generateStockPrices() {
yield { exchange: 'NYSE', symbol: 'AAPL', price: 170.50 };
yield { exchange: 'LSE', symbol: 'AAPL', price: 170.75 };
await new Promise(resolve => setTimeout(resolve, 50));
yield { exchange: 'TSE', symbol: 'AAPL', price: 170.60 };
}
async function main() {
const stockPrices = generateStockPrices();
// Use scan to calculate a running average price
const runningAverages = scan(
stockPrices,
(acc, priceUpdate) => {
const { total, count } = acc;
return { total: total + priceUpdate.price, count: count + 1 };
},
{ total: 0, count: 0 }
);
for await (const averageData of runningAverages) {
const averagePrice = averageData.total / averageData.count;
console.log(`Running average price: ${averagePrice.toFixed(2)}`);
}
}
main();
இந்த எடுத்துக்காட்டில், `accumulator` செயல்பாடு விலைகளின் இயங்கும் மொத்தத்தையும் பெறப்பட்ட புதுப்பிப்புகளின் எண்ணிக்கையையும் கணக்கிடுகிறது. இறுதி சராசரி விலை இந்த திரட்டப்பட்ட மதிப்புகளிலிருந்து கணக்கிடப்படுகிறது. இது வெவ்வேறு உலகளாவிய சந்தைகளில் பங்கு விலையின் நிகழ்நேரப் பார்வையை வழங்குகிறது.
5. உலகளவில் இணையதளப் போக்குவரத்தை பகுப்பாய்வு செய்தல்
உலகெங்கிலும் உள்ள சேவையகங்களிலிருந்து இணையதள வருகைத் தரவுகளின் ஸ்ட்ரீம்களைப் பெறும் ஒரு உலகளாவிய வலை பகுப்பாய்வு தளத்தை கற்பனை செய்து பாருங்கள். ஒவ்வொரு தரவுப் புள்ளியும் இணையதளத்தைப் பார்வையிடும் ஒரு பயனரைக் குறிக்கிறது. `scan`-ஐப் பயன்படுத்தி, ஒரு நாட்டிற்குப் பக்கக் காட்சிகளின் போக்கை நிகழ்நேரத்தில் பகுப்பாய்வு செய்யலாம். தரவு இதுபோன்று இருக்கும் என்று வைத்துக்கொள்வோம்: `{ country: "US", page: "homepage", timestamp: 1678886400 }`.
async function* generateWebsiteVisits() {
yield { country: 'US', page: 'homepage', timestamp: Date.now() };
yield { country: 'CA', page: 'product', timestamp: Date.now() };
yield { country: 'UK', page: 'blog', timestamp: Date.now() };
yield { country: 'US', page: 'product', timestamp: Date.now() };
}
async function main() {
const visitStream = generateWebsiteVisits();
const pageViewCounts = scan(
visitStream,
(acc, visit) => {
const { country } = visit;
const newAcc = { ...acc };
newAcc[country] = (newAcc[country] || 0) + 1;
return newAcc;
},
{}
);
for await (const counts of pageViewCounts) {
console.log('Page view counts by country:', counts);
}
}
main();
இங்கே, `accumulator` செயல்பாடு ஒவ்வொரு நாட்டிற்கும் ஒரு கவுண்டரைப் புதுப்பிக்கிறது. புதிய வருகைத் தரவு வரும்போது ஒவ்வொரு நாட்டிற்கும் திரட்டப்பட்ட பக்கக் காட்சிகளின் எண்ணிக்கையை வெளியீடு காண்பிக்கும்.
`scan`-ஐப் பயன்படுத்துவதன் நன்மைகள்
`scan` ஹெல்பர் அசிங்க்ரோனஸ் தரவு ஸ்ட்ரீம்களுடன் பணிபுரியும் போது பல நன்மைகளை வழங்குகிறது:
- Declarative Style: `scan` திரட்டல் செயலாக்க தர்க்கத்தை ஒரு அறிவிப்பு மற்றும் சுருக்கமான வழியில் வெளிப்படுத்த உங்களை அனுமதிக்கிறது, இது குறியீட்டின் வாசிப்புத்திறன் மற்றும் பராமரிப்புத்தன்மையை மேம்படுத்துகிறது.
- Asynchronous Handling: இது அக்குமுலேட்டர் செயல்பாட்டிற்குள் அசிங்க்ரோனஸ் செயல்பாடுகளை தடையின்றி கையாளுகிறது, இது I/O-சார்ந்த பணிகளை உள்ளடக்கிய சிக்கலான சூழ்நிலைகளுக்கு ஏற்றதாக அமைகிறது.
- Real-time Processing: `scan` தரவு ஸ்ட்ரீம்களின் நிகழ்நேர செயலாக்கத்தை செயல்படுத்துகிறது, மாற்றங்கள் நிகழும்போது அவற்றுக்கு எதிர்வினையாற்ற உங்களை அனுமதிக்கிறது.
- Composability: சிக்கலான தரவு செயலாக்க குழாய்களை உருவாக்க மற்ற அசிங்க் இட்டரேட்டர் ஹெல்பர்களுடன் இதை எளிதாக இணைக்க முடியும்.
`scan`-ஐ செயல்படுத்துதல் (கிடைக்கவில்லை என்றால்)
சில லைப்ரரிகள் ஒரு உள்ளமைக்கப்பட்ட `scan` ஹெல்பரை வழங்கினாலும், தேவைப்பட்டால் நீங்களே எளிதாக ஒன்றை செயல்படுத்தலாம். இங்கே ஒரு எளிய செயல்படுத்தல்:
async function* scan(sourceIterator, accumulator, initialValue) {
let accumulatedValue = initialValue;
let first = true;
for await (const value of sourceIterator) {
if (first && initialValue === undefined) {
accumulatedValue = value;
first = false;
} else {
accumulatedValue = accumulator(accumulatedValue, value);
}
yield accumulatedValue;
}
}
இந்தச் செயல்படுத்தல் மூல இட்டரேட்டரின் மீது செயல்பட்டு, ஒவ்வொரு மதிப்பிற்கும் அக்குமுலேட்டர் செயல்பாட்டைப் பயன்படுத்துகிறது, திரட்டப்பட்ட முடிவை அளிக்கிறது. `initialValue` வழங்கப்படாத நிலையை, மூல இட்டரேட்டரிலிருந்து முதல் மதிப்பை ஆரம்ப மதிப்பாகப் பயன்படுத்தி இது கையாளுகிறது.
`reduce` உடன் ஒப்பீடு
`scan`-ஐ `reduce`-லிருந்து வேறுபடுத்துவது முக்கியம். இரண்டும் இட்டரேட்டர்களில் செயல்பட்டு ஒரு அக்குமுலேட்டர் செயல்பாட்டைப் பயன்படுத்தினாலும், அவற்றின் நடத்தை மற்றும் வெளியீட்டில் வேறுபடுகின்றன.
- `scan` ஒவ்வொரு மறு செய்கைக்கும் திரட்டப்பட்ட மதிப்பை வெளியிடுகிறது, இது திரட்டலின் இயங்கும் வரலாற்றை வழங்குகிறது.
- `reduce` இட்டரேட்டரில் உள்ள அனைத்து கூறுகளையும் செயலாக்கிய பிறகு இறுதி திரட்டப்பட்ட மதிப்பை மட்டுமே வெளியிடுகிறது.
எனவே, திரட்டலின் இடைநிலை நிலைகளைக் கண்காணிக்க வேண்டிய சூழ்நிலைகளுக்கு `scan` பொருத்தமானது, அதேசமயம் இறுதி முடிவு மட்டுமே தேவைப்படும்போது `reduce` பொருத்தமானது.
பிழை கையாளுதல்
அசிங்க்ரோனஸ் இட்டரேட்டர்கள் மற்றும் `scan`-உடன் பணிபுரியும் போது, பிழைகளை நேர்த்தியாக கையாள்வது முக்கியம். மறு செய்கை செயல்முறையின் போது அல்லது அக்குமுலேட்டர் செயல்பாட்டிற்குள் பிழைகள் ஏற்படலாம். இந்த பிழைகளைப் பிடிக்கவும் கையாளவும் நீங்கள் `try...catch` தொகுதிகளைப் பயன்படுத்தலாம்.
async function* generatePotentiallyFailingData() {
yield 1;
yield 2;
throw new Error('Something went wrong!');
yield 3;
}
async function main() {
const dataStream = generatePotentiallyFailingData();
try {
const accumulatedData = scan(dataStream, (acc, value) => acc + value, 0);
for await (const data of accumulatedData) {
console.log(data);
}
} catch (error) {
console.error('An error occurred:', error);
}
}
main();
இந்த எடுத்துக்காட்டில், `try...catch` தொகுதி `generatePotentiallyFailingData` இட்டரேட்டரால் வீசப்பட்ட பிழையைப் பிடிக்கிறது. பின்னர் நீங்கள் பிழையை அதற்கேற்ப கையாளலாம், அதாவது அதைப் பதிவு செய்வது அல்லது செயல்பாட்டை மீண்டும் முயற்சிப்பது போன்றவை.
முடிவுரை
`scan` ஹெல்பர் என்பது ஜாவாஸ்கிரிப்ட் அசிங்க் இட்டரேட்டர்களில் அசிங்க்ரோனஸ் திரட்டல் செயலாக்கத்தைச் செய்வதற்கான ஒரு சக்திவாய்ந்த கருவியாகும். இது சிக்கலான தரவு மாற்றங்களை ஒரு அறிவிப்பு மற்றும் சுருக்கமான முறையில் வெளிப்படுத்தவும், அசிங்க்ரோனஸ் செயல்பாடுகளை நேர்த்தியாக கையாளவும், மற்றும் தரவு ஸ்ட்ரீம்களை நிகழ்நேரத்தில் செயலாக்கவும் உங்களை அனுமதிக்கிறது. அதன் செயல்பாடு மற்றும் பயன்பாட்டு வழக்குகளைப் புரிந்துகொள்வதன் மூலம், மேலும் வலுவான மற்றும் திறமையான அசிங்க்ரோனஸ் பயன்பாடுகளை உருவாக்க `scan`-ஐப் பயன்படுத்தலாம். இயங்கும் மொத்தங்களைக் கணக்கிடுவது, தரவை அரேக்களில் திரட்டுவது, ரேட் லிமிட்டர்களை செயல்படுத்துவது, அல்லது நிகழ்நேர தரவு திரட்டிகளை உருவாக்குவது என எதுவாக இருந்தாலும், `scan` உங்கள் குறியீட்டை எளிதாக்கி அதன் ஒட்டுமொத்த செயல்திறனை மேம்படுத்தும். பிழை கையாளுதலைக் கருத்தில் கொள்ளவும், உங்கள் அசிங்க்ரோனஸ் தரவு ஸ்ட்ரீம்களைச் செயலாக்கும் போது இடைநிலை திரட்டப்பட்ட மதிப்புகளுக்கான அணுகல் தேவைப்படும்போது `reduce`-ஐ விட `scan`-ஐத் தேர்ந்தெடுக்கவும் நினைவில் கொள்ளுங்கள். RxJS போன்ற லைப்ரரிகளை ஆராய்வது, எதிர்வினை நிரலாக்க முன்னுதாரணங்களுக்குள் `scan`-இன் உங்கள் புரிதலையும் நடைமுறைப் பயன்பாட்டையும் மேலும் மேம்படுத்தும்.